/**
*  
* @Function 数据催收服务实现类 
* @ProjectName credit-data-platform 
* @PackageName com.py.credit.service.impl    
* @FileName TaskRemindServiceImpl.java    
* @Date 2018年5月9日上午10:31:07
* @Author Min DongXv
* @Copyright (c) 2018, 金电联行 All Rights Reserved.   
*   
*/
package com.py.credit.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.py.credit.common.logs.AccessLogger;
import com.py.credit.common.rest.RestServiceResult;
import com.py.credit.dao.TaskRemindDao;
import com.py.credit.entity.MsgContentEntity;
import com.py.credit.entity.MsgDetailEntity;
import com.py.credit.entity.SubscribeContentCount;
import com.py.credit.entity.SubscribeCount;
import com.py.credit.entity.SubscriptionRelation;
import com.py.credit.entity.SysUser;
import com.py.credit.entity.TaskRemind;
import com.py.credit.service.RemoteBaseService;
import com.py.credit.service.TaskRemindService;
import com.py.credit.utils.DateUtil;
import com.py.credit.utils.SQLBuilder;
import com.py.framework.core.common.Page;

/**
 * 
 * @Function 数据催收服务实现类
 * @ClassName TaskRemindServiceImpl
 * @Date 2018年5月9日 上午10:31:07
 * @Author Min DongXv
 * 
 */
@Service
public class TaskRemindServiceImpl implements TaskRemindService {

	private static final String MOUTH = "M";
	private static final String QUARTER = "Q";
	private static final String YEAR = "Y";
	/** 数据催收类型 */
	private static final String C = "C";
	/** 任务提醒类型 */
	private static final String T = "T";

	private static final int NUM_1000 = 1000;

	@Autowired
	private TaskRemindDao taskRemindDao;

	@Autowired
	private RemoteBaseService remoteBaseService;

	/**
	 *
	 * @Function 分页查询数据催收信息
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName selectTaskRemindByConditionForPage
	 * @param columns
	 * @param additionalColumns
	 * @param condition
	 * @param page
	 * @param type
	 *            类型 C:数据催收 T:任务提醒
	 * @return
	 * @Date 2018年5月9日 上午10:33:29
	 * @Author Min DongXv
	 *
	 */
	@Override
	public List<Map<String, Object>> selectTaskRemindByConditionForPage(List<String> columns,
			String[] additionalColumns, String condition, Page page, String type, SysUser userInfo) {
		List<String> conditions = SQLBuilder.createConditionSql(condition);
		Long deptId = userInfo.getOfficeId();
		// 非普通用户通过区域限制
		if (userInfo.getUserType() > 1) {
			deptId = null;
		}
		return taskRemindDao.selectTaskRemindByConditionForPage(columns, additionalColumns, conditions, page, type,
				deptId, userInfo.getAreaId());
	}

	/**
	 *
	 * @Function 新增任务提醒
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName addTaskRemind
	 * @param taskRemind
	 * @return
	 * @Date 2018年5月9日 上午10:33:29
	 * @Author Min DongXv
	 *
	 */
	@Override
	public int addTaskRemind(TaskRemind taskRemind) {
		return taskRemindDao.addTaskRemind(taskRemind);
	}

	/**
	 * 
	 *
	 * @Function 更新任务提醒数据状态
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName updateTaskRemind
	 * @param id
	 * @Date 2018年5月11日 下午4:39:37
	 * @Author Min DongXv
	 *
	 */
	@Override
	public void updateTaskRemind(Integer id, String status) {
		taskRemindDao.updateTaskRemind(id, status);
	}

	/**
	 * 
	 * @Function 获取所有更新频率为月季年的订阅人和资源关系
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName selectAllSubscriptionRelation
	 * @return
	 * @Date 2018年5月11日 上午10:49:33
	 * @Author Min DongXv
	 *
	 */
	@Override
	public List<SubscriptionRelation> selectAllSubscriptionRelation() {
		return taskRemindDao.selectAllSubscriptionRelation();
	}

	/**
	 * 
	 * @Function 获取两年内订阅人上报的数据统计
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName selectSubscriberIdForYear
	 * @return
	 * @Date 2018年5月11日 上午9:57:42
	 * @Author Min DongXv
	 *
	 */
	@Override
	public List<SubscribeCount> selectSubscriberIdForYear() {
		return taskRemindDao.selectSubscriberIdForYear();
	}

	/**
	 * 
	 * @Function 数据处理
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName dataDeal
	 * @return
	 * @Date 2018年5月11日 上午9:57:42
	 * @Author Min DongXv
	 *
	 */
	@Override
	public void dataRemind(int advanceDay, String type) {
		List<SubscribeContentCount> result = new ArrayList<SubscribeContentCount>();
		// 获取订阅关系
		List<SubscriptionRelation> relations = selectAllSubscriptionRelation();
		// 订阅关系过滤
		List<SubscriptionRelation> relationResult = subscriptionRelationFilter(relations, advanceDay);
		// 数据组装
		result = dataAssemble(result, relationResult);
		List<TaskRemind> taskList = new ArrayList<TaskRemind>();
		if (!CollectionUtils.isEmpty(result)) {
			List<MsgContentEntity> msgs = new ArrayList<MsgContentEntity>(result.size());
			for (SubscribeContentCount count : result) {
				if (null != count && !CollectionUtils.isEmpty(count.getSourceCounts())) {
					TaskRemind taskRemind = new TaskRemind();
					taskRemind.setInfoId(count.getInfoId());
					taskRemind.setInfoName(count.getInfoName());
					taskRemind.setInfoVersion(count.getVersionName());
					taskRemind.setSubscriptionRegion(StringUtils.isNotEmpty(count.getSubscriptionRegion())
							? Integer.valueOf(count.getSubscriptionRegion()) : 0);
					taskRemind.setSubscriberId(count.getSubscriberId());
					taskRemind.setType(type);
					taskRemind.setSourceCounts(count.getSourceCounts());
					taskList.add(taskRemind);
				}
			}
			// 分批次批量插入
			if (!CollectionUtils.isEmpty(taskList)) {
				List<TaskRemind> taskListResult = new ArrayList<TaskRemind>(taskList.size());
				AccessLogger.info("数据催收和任务提醒定时任务批量插入数据开始", "TaskRemindService#dataRemind", null);
				if (taskList.size() > NUM_1000) {
					int num = taskList.size() / NUM_1000;
					for (int i = 0; i < num; i++) {
						List<TaskRemind> taskListTemp = taskList.subList(0 + i * NUM_1000, 999 + i * NUM_1000);
						taskRemindDao.batchAddTaskRemind(taskListTemp);
						taskListResult.addAll(taskListTemp);
					}
					List<TaskRemind> taskListTemp = taskList.subList(num * NUM_1000, taskList.size());
					taskRemindDao.batchAddTaskRemind(taskListTemp);
					taskListResult.addAll(taskListTemp);
				} else {
					taskRemindDao.batchAddTaskRemind(taskList);
					taskListResult = taskList;
				}
				for (TaskRemind r : taskListResult) {
					// 组装系统消息
					msgs = assembleSysMsgInfo(msgs, r);
				}
				AccessLogger.info("数据催收和任务提醒定时任务批量插入数据结束", "TaskRemindService#dataRemind", null);
				// 发送站内信
				if (!CollectionUtils.isEmpty(msgs)) {
					AccessLogger.info("数据催收和任务提醒定时任务发送站内信开始", "TaskRemindService#dataRemind", msgs.toString(), null, 0);
					Future<HttpResponse> response = remoteBaseService.sendMsg(msgs, null);
					AccessLogger.info("数据催收和任务提醒定时任务发送站内信结束", "TaskRemindService#dataRemind", msgs.toString(),
							null != response ? response.toString() : null, 0);
				}
			}
		}
	}

	/**
	 * 
	 * @Function 组装系统消息内容
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName assembleSysMsgInfo
	 * @return
	 * @Date 2018年5月11日 上午9:57:42
	 * @Author Min DongXv
	 *
	 */
	private List<MsgContentEntity> assembleSysMsgInfo(List<MsgContentEntity> msgs, TaskRemind remind) {
		MsgContentEntity entity = new MsgContentEntity();
		String type = remind.getType();
		// 数据催收
		if (C.equals(type)) {
			entity.setMsgTitle("数据上报已超期");
			entity.setMsgType(3);
			entity.setBusExt(String.valueOf(remind.getId()));
			List<MsgDetailEntity> detailList = new ArrayList<MsgDetailEntity>(1);
			MsgDetailEntity detail = new MsgDetailEntity(1, Long.valueOf(remind.getSubscriberId()));
			detailList.add(detail);
			entity.setDetails(detailList);
		}
		// 任务提醒
		if (T.equals(type)) {
			entity.setMsgTitle("数据上报时间将到期");
			entity.setMsgType(2);
			entity.setBusExt(String.valueOf(remind.getId()));
			List<MsgDetailEntity> detailList = new ArrayList<MsgDetailEntity>(1);
			MsgDetailEntity detail = new MsgDetailEntity(1, Long.valueOf(remind.getSubscriberId()));
			detailList.add(detail);
			entity.setDetails(detailList);
		}
		StringBuffer sb = new StringBuffer();
		for (SubscribeCount s : remind.getSourceCounts()) {
			sb.append(s.getResuorceName()).append("、");
			if (sb.length() > 250) {
				break;
			}
		}
		String msg = "";
		if (sb.length() > 0) {
			msg = sb.substring(0, sb.length() - 1);
		}
		msg = msg + "等资源未上报，请尽快上报数据！";
		entity.setMsgContent(msg);
		msgs.add(entity);
		return msgs;
	}

	/**
	 * 
	 * @Function 数据组装
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName dataAssemble
	 * @return
	 * @Date 2018年5月11日 上午9:57:42
	 * @Author Min DongXv
	 *
	 */
	private List<SubscribeContentCount> dataAssemble(List<SubscribeContentCount> result,
			List<SubscriptionRelation> relationResult) {
		if (!CollectionUtils.isEmpty(relationResult)) {
			List<SubscribeCount> counts = selectSubscriberIdForYear();
			Map<String, SubscribeContentCount> map = new HashMap<String, SubscribeContentCount>();
			for (SubscriptionRelation relation : relationResult) {
				// 组装催收记录数据，订阅目录和订阅人关系唯一
				String id = relation.getInfoId() + "|" + relation.getSubscriberId();
				SubscribeContentCount contentInfo = null;
				List<SubscribeCount> sourceCount = null;
				if (map.containsKey(id)) {
					contentInfo = map.get(id);
					sourceCount = contentInfo.getSourceCounts();
				} else {
					contentInfo = new SubscribeContentCount();
					sourceCount = new ArrayList<SubscribeCount>();
					contentInfo.setSourceCounts(sourceCount);
					// bean拷贝
					BeanUtils.copyProperties(relation, contentInfo);
					map.put(id, contentInfo);
				}
				// 默认资源未上报
				boolean flag = true;
				for (SubscribeCount count : counts) {
					// 对应订阅人和资源ID的数据
					if (null != count && relation.getResourceId().equals(count.getTarget())
							&& relation.getSubscriberId().equals(count.getManagerId())) {
						if (count.getEndTime().compareTo(relation.getStartDate()) > 0
								&& count.getEndTime().compareTo(relation.getEndDate()) < 0) {
							// 在时间段内有资源上报
							flag = false;
							break;
						}
					}
				}
				if (flag) {
					SubscribeCount count = new SubscribeCount();
					count.setTarget(relation.getResourceId());
					count.setManagerId(relation.getSubscriberId());
					count.setResuorceName(relation.getResourceName());
					sourceCount.add(count);
				}
			}
			for (Map.Entry<String, SubscribeContentCount> entry : map.entrySet()) {
				result.add(entry.getValue());
			}
		}
		return result;
	}

	/**
	 *
	 * @Function 订阅关系过滤
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName subscriptionRelationFilter
	 * @return
	 * @Date 2018年5月9日 上午10:33:29
	 * @Author Min DongXv
	 *
	 */
	private List<SubscriptionRelation> subscriptionRelationFilter(List<SubscriptionRelation> relations,
			int advanceDay) {
		List<SubscriptionRelation> relationResult = new ArrayList<SubscriptionRelation>();
		// 订阅关系清理
		if (!CollectionUtils.isEmpty(relations)) {
			for (SubscriptionRelation relation : relations) {
				if (null != relation && null != relation.getSubscriptionTime()) {
					// 日期计算
					Map<String, Date> dates = dateCount(relation.getSubscriptionTime(), relation.getUpdateFrequency(),
							advanceDay);
					if (null != dates) {
						relation.setStartDate(dates.get("startDate"));
						relation.setEndDate(dates.get("endDate"));
						relationResult.add(relation);
					}
				}
			}
		}
		// // 填充姓名
		// if (!CollectionUtils.isEmpty(relationResult)) {
		// Set<Integer> userIds = new HashSet<Integer>();
		// for (SubscriptionRelation relation : relationResult) {
		// if (StringUtils.isNotEmpty(relation.getRealName())) {
		// userIds.add(Integer.parseInt(relation.getRealName()));
		// }
		// }
		// // 通过用户ID获取用户名称
		// RestServiceResult<Map<String, String>> userInfo =
		// remoteBaseService.getUserName(userIds);
		// Map<String, String> users = userInfo.getData();
		// // 填充姓名信息
		// for (SubscriptionRelation relation : relationResult) {
		// if (null != relation) {
		// relation.setRealName(users.get(relation.getRealName()));
		// }
		// }
		// }
		return relationResult;
	}

	/**
	 *
	 * @Function 获取订阅数据统计周期
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName dateCount
	 * @param subscriptionTime
	 *            订阅时间
	 * @param type
	 *            更新频率 M:每月,Q:每季度,Y:每年
	 * @param advanceDay
	 *            提前天数
	 * @return
	 * @Date 2018年5月9日 上午10:33:29
	 * @Author Min DongXv
	 *
	 */
	private Map<String, Date> dateCount(Date subscriptionTime, String type, int advanceDay) {
		Date currentDate = new Date();
		Calendar current = new GregorianCalendar();
		current.setTime(currentDate);
		current.set(current.get(Calendar.YEAR), current.get(Calendar.MONTH), current.get(Calendar.DAY_OF_MONTH), 0, 0,
				0);
		currentDate = current.getTime();
		// 传入时间
		Calendar subscriptionDate = new GregorianCalendar();
		subscriptionDate.setTime(subscriptionTime);
		Calendar endDate = new GregorianCalendar();
		SimpleDateFormat df = new SimpleDateFormat(DateUtil.YYYY_MM_DD);
		endDate.setTime(currentDate);
		// 设置结束时间的日为传入时间的日
		endDate.set(Calendar.DAY_OF_MONTH, subscriptionDate.get(Calendar.DAY_OF_MONTH));
		// 任务提醒时间比当前时间小
		if ("T".equals(type) && endDate.compareTo(current) < 1) {
			endDate.add(Calendar.MONTH, 1);
		}
		// 结束时间向前追溯{advanceDay}天
		endDate.set(Calendar.DAY_OF_MONTH, endDate.get(Calendar.DAY_OF_MONTH) - advanceDay);
		// 当天需要提醒的日期进行时间计算
		if (df.format(endDate.getTime()).equals(df.format(current.getTime()))) {
			Calendar startDate = new GregorianCalendar();
			startDate.setTime(currentDate);
			// 设置开始时间的日为传入时间的日
			startDate.set(Calendar.DAY_OF_MONTH, subscriptionDate.get(Calendar.DAY_OF_MONTH));
			Map<String, Date> timeRange = new HashMap<String, Date>(2);
			if (MOUTH.equals(type)) {
				// 更新频率为月度
				// 开始时间向前追溯1个月
				startDate.add(Calendar.MONTH, -1);
			} else if (QUARTER.equals(type)) {
				// 更新频率为季度
				// 开始时间向前追溯3个月
				startDate.add(Calendar.MONTH, -3);
			} else if (YEAR.equals(type)) {
				// 更新频率为年度
				// 开始时间向前追溯1年
				startDate.add(Calendar.YEAR, -1);
			}
			timeRange.put("startDate", startDate.getTime());
			timeRange.put("endDate", endDate.getTime());
			return timeRange;
		} else {
			return null;
		}
	}

	/**
	 * 
	 * @Function 部门绩效统计未完成部门进行数据催收信息发送
	 * @FileName TaskRemindServiceImpl.java
	 * @MethodName getUnfinishDept
	 * @Date 2018年7月20日 下午3:07:52
	 * @Author Min DongXv
	 *
	 */
	@Override
	public void dataUnfinishRemind() {
		// 获取部门绩效统计未完成的部门数据
		List<Map<String, Object>> data = taskRemindDao.getUnfinishDept();
		Set<String> deptIds = new HashSet<String>();
		if (!CollectionUtils.isEmpty(data)) {
			for (Map<String, Object> m : data) {
				if (null != m && null != m.get("isAchieve")) {
					deptIds.add(String.valueOf(m.get("deptId")));
				}
			}
		}
		// 获取所有部门管理员信息
		RestServiceResult<List<SysUser>> users = remoteBaseService.getDeptAdminUsers(null, null);
		if (!CollectionUtils.isEmpty(deptIds) && RestServiceResult.CODE_SUCCESS == users.getCode()
				&& !CollectionUtils.isEmpty(users.getData())) {
			List<MsgDetailEntity> detailList = new ArrayList<MsgDetailEntity>();
			for (SysUser user : users.getData()) {
				if (deptIds.contains(String.valueOf(user.getOfficeId()))) {
					// 添加部门负责人
					if (null != user.getId()) {
						MsgDetailEntity detail = new MsgDetailEntity(1, user.getId());
						detailList.add(detail);
					}
				}
			}
			// 部门负责人列表不为空
			if (!CollectionUtils.isEmpty(detailList)) {
				MsgContentEntity entity = new MsgContentEntity();
				entity.setMsgTitle("本期还未数据上报");
				entity.setMsgType(3);
				entity.setMsgContent("你部门负责归集的信息资源表，在数据更新周期内无数据上报，请按要求进行数据报送");
				entity.setDetails(detailList);
				AccessLogger.info("部门绩效统计未上报数据定时任务发送站内信开始", "TaskRemindService#getUnfinishDept", entity.toString(),
						null, 0);
				List<MsgContentEntity> msgList = new ArrayList<MsgContentEntity>(1);
				msgList.add(entity);
				Future<HttpResponse> response = remoteBaseService.sendMsg(msgList, null);
				AccessLogger.info("部门绩效统计未上报数据定时任务发送站内信开始", "TaskRemindService#getUnfinishDept", entity.toString(),
						null != response ? response.toString() : null, 0);
			}
		}
	}
}
